package com.alan.netty.rpc.v1;

import com.alan.netty.rpc.common.ClassUtils;
import com.alan.netty.rpc.common.RpcException;
import com.alan.netty.rpc.common.RpcRequest;
import com.alan.netty.rpc.common.RpcResponse;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author weiBin
 * @date 2018/11/27
 */
public class RpcBuilder {
    Map<String, Object> services = new ConcurrentHashMap<>();
    Map<String, Class> interfaces = new ConcurrentHashMap<>();

    public void publishService(Class serviceInterface, Object service) {
        String interfaceName = serviceInterface.getName();
        if (services.containsKey(interfaceName) || interfaces.containsKey(interfaceName)) {
            throw new RpcException("serviceInterface has been already registered......");
        }
        services.put(interfaceName, service);
        interfaces.put(interfaceName, serviceInterface);
    }

    public RpcResponse invokeService(RpcRequest request) {
        RpcResponse response = new RpcResponse();
        String serviceName = request.getServiceName();
        String methodName = request.getMethodName();
        response.setId(request.getId());
        response.setMethodName(methodName);
        response.setServiceName(serviceName);
        Method method = null;
        String[] parameterTypeNames = request.getParameterTypeNames();
        try {
            Class<?>[] classes = new Class[parameterTypeNames.length];
            for (int i = 0; i < parameterTypeNames.length; i++) {
                classes[i] = ClassUtils.getClass(parameterTypeNames[i]);
            }
            Class serviceInterface = interfaces.get(serviceName);
            method = serviceInterface.getMethod(methodName, classes);
            response.setResult(method.invoke(services.get(serviceName), request.getArgs()));
        } catch (Exception e) {
            throw new RpcException(e.getMessage(), e);
        }
        return response;
    }
}
